package org.tigris.mappedlexer.implementation;

import org.tigris.mappedlexer.*;
import org.tigris.mappedlexer.io.CharInputSequence;
import org.tigris.mappedlexer.io.CharOutputSequence;
import org.tigris.mappedlexer.io.implementation.*;
import org.tigris.mappedlexer.validator.*;

/**
 * Selectively write tokens to the output files.
 * 
 * @author Sam Huang
 */
public class SimpleMappedLexer extends SimpleLexer implements MappedLexer {

	protected boolean dump = true;

	protected String inputFileName = "";

	protected String outputFileName = "";

	protected CharOutputSequence outputSequence = null;

	/**
	 * The default constructor.
	 * 
	 */
	public SimpleMappedLexer() throws Exception {
		super();
	}

	/**
	 * Constructor with default output stream to console.
	 * 
	 * @param s
	 *            the character input sequence
	 */
	public SimpleMappedLexer(CharInputSequence s) {
		super(s);
		setCharOutputSequence(ConsoleCharOutputSequence.getInstance());
	}

	/**
	 * Constructor with defined character input sequence and output sequence.
	 * 
	 * @param cs
	 *            the input sequence
	 * @param outputSource
	 *            the output sequence
	 * @throws Exception
	 */
	public SimpleMappedLexer(CharInputSequence cs,
			CharOutputSequence outputSource) throws Exception {
		super(cs);
		setCharOutputSequence(outputSource);
	}

	/**
	 * Close the lexer with the related input and output sequence.
	 * 
	 */
	@Override
	public void close() throws Exception {
		super.close();
		outputSequence.close();
	}

	/**
	 * Writes the current token to output sequence.
	 * 
	 * @param dump
	 *            true to dump, false to not.
	 */
	public void dump(boolean dump) {
		if (dump && this.dump && outputSequence != null) {
			outputSequence.append(tk);
			// printer.print(" ");
		}
	}

	/**
	 * Set the lexer with the given steps ahead.
	 * 
	 * @param length
	 *            the steps to jump
	 * 
	 */
	@Override
	public String forward(int length) throws Exception {
		tk = super.forward(length);
		dump(true);
		return tk;
	}

	/**
	 * Set the lexer to jump with the length of the parametered token ahead.
	 * 
	 * @param token
	 *            a token to define the length of jumpping
	 */
	@Override
	public String forward(String token) throws Exception {
		tk = super.forward(token);
		dump(true);
		return tk;
	}

	/**
	 * Get the next token with the constraints.
	 * 
	 * @param validators
	 *            the constraints
	 */
	public String forwardUntil(boolean dump, char chr) throws Exception {
		tk = super.forwardUntil(chr);
		dump(dump);
		return tk;
	}

	/**
	 * Forward the lexer until reaches the desired character.
	 * 
	 */
	@Override
	public String forwardUntil(char chr) throws Exception {
		tk = super.forwardUntil(chr);
		dump(true);
		return tk;
	}

	/**
	 * Get the next token with the constraints.
	 * 
	 * @param validators
	 *            the constraints
	 */
	@Override
	public String forwardUntil(String token) throws Exception {
		tk = super.forwardUntil(token);
		dump(true);
		return tk;
	}

	/**
	 * Get the next token with the constraints.
	 * 
	 * @param validators
	 *            the constraints
	 */
	@Override
	public String forwardUntil(Validator v)throws Exception {
		tk = super.forwardUntil(v);
		dump(true);
		return tk;
	}

	/**
	 * Get the output sequence.
	 * 
	 */
	public CharOutputSequence getCharOutputSequence() {
		return this.outputSequence;
	}

	/**
	 * Get the next character by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	public String nextchar(boolean dump, char chr) throws Exception {
		tk = String.valueOf(super.nextchar(chr));
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	public String nexttok(boolean dump) throws Exception{
		tk = super.nexttok();
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	public String nexttok(boolean dump, int length) throws Exception{
		tk = super.nexttok(length);
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	public String nexttok(boolean dump, String... strings)throws Exception {
		tk = super.nexttok(strings);
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	public String nexttok(boolean dump, String[] t, Validator[] v)
			throws Exception {
		tk = super.nexttok(t, v);
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	public String nexttok(boolean dump, Validator... verifiers)throws Exception {
		tk = super.nexttok(verifiers);
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param length
	 *            the expected length of the token
	 */
	@Override
	public String nexttok(int length) throws Exception{
		tk = super.nexttok(length);
		dump(dump);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param expected
	 *            the expected tokens
	 */
	@Override
	public String nexttok(String... expected) throws Exception{
		tk = super.nexttok(expected);
		dump(true);
		return tk;
	}

	/**
	 * Get the next token by the constraints.
	 * 
	 * @param t
	 *            the expected tokens
	 * @param v
	 *            the expected types of tokens
	 */
	@Override
	public String nexttok(String[] t, Validator[] v) throws Exception {
		return this.nexttok(true, t, v);
	}

	/**
	 * Get the next token with the constraints.
	 * 
	 * @param validators
	 *            the constraints
	 */
	@Override
	public String nexttok(Validator... validators) throws Exception{
		tk = super.nexttok(validators);
		dump(true);
		return tk;
	}

	/**
	 * Prints the character to the output sequence.
	 * 
	 * @param chr
	 * @return
	 */
	public SimpleMappedLexer print(char chr) {
		if (this.dump && outputSequence != null) {
			outputSequence.append(chr);
		}
		return this;
	}

	/**
	 * Prints the message to the output sequence.
	 * 
	 */
	public SimpleMappedLexer print(String message) {
		if (this.dump && outputSequence != null) {
			outputSequence.append(message);
			// printer.print(" ");
		}
		return this;
	}

	/**
	 * Set the output sequence.
	 * 
	 */
	public void setCharOutputSequence(CharOutputSequence ss)
			throws UnsupportedOperationException {
		this.outputSequence = ss;
	}

	/**
	 * Get the dump flag.
	 * 
	 * @return the dump
	 */
	public boolean getDump() {
		return this.dump;
	}

	/**
	 * Set the flag to write.
	 * 
	 * @param dump
	 *            flag to dump
	 * 
	 */
	public void setDump(boolean dump) {
		this.dump = dump;
	}

	/**
	 * Skip the token stream until reaches the character.
	 * 
	 * @param dump
	 *            wheter or not to writes the skipped characters to the output
	 *            stream
	 * @param chr
	 *            the stopped character
	 */
	public String skip(boolean dump, char chr) throws Exception {
		tk = super.skipTo(chr);
		dump(dump);
		return tk;
	}
}
